/*
 * Paso 1 (EASY MODE)
 Crear un proyecto en Netbeans
 Configurar el proyecto para que se pueda utilizar los tests
 Requerimientos iniciales:
 El método add puede aceptar 0, 1 o 2 números, y devolverá la suma de estos, en caso la cadena ingresada sea sea vacía devolverá. Por ejemplo "" => 0 o "1" => 1 o "1,2" => 3.
 Algunos valores incorrectos son: 
 Escribir tests:
 probarCadenaVacia
 probarCadenaConUnValor
 probarDosValores
 probarFormatoIncorrecto (Caso negativo)

 Paso 2 (NORMAL MODE)
 El método add puede manejar una cantidad ilimitada de números
 El método puede manejar saltos de líneas en vez de comas
 Las siguientes entradas son válidas:
 1\n2,3
 1\n2\n3
 Entradas no válidas
 1,\n (Dado que no hay un número con que sumar)
 Escribir tests
 probarCadenaConTresValores
 probarCadenaConSeisValores
 probarSaltoLineaVálidos
 probarSaltoLineaInvalidos

 Paso 3 (INSANE MODE)
 El método add debe soportar usar cualquier tipo de delimitador. Donde el patrón es el siguiente 
 //[Nuevo Delimitador]\n[number][; o \n][number]
 Ejemplo  “//;\n1;2;3” (de ejemplo el nuevo delimitador es ; y está definido entre // y \n 
 Enviar números negativos debe lanzar una excepción
 Escribir tests:
 probarCadenaNuevoDelimitador
 probarCadenaNumeroNegativos

 */
package edu.upc.poo.stringcalc;

import java.util.ArrayList;
import java.util.Iterator;

/**
 *
 * @author heraldo
 */
public class StringCalc {
    /*
     *  Paso 1 (EASY MODE)
     * Requerimientos iniciales:
     * El método add puede aceptar 0, 1 o 2 números, y
     * devolverá la suma de estos, en caso la cadena
     * ingresada sea sea vacía devolverá. Por ejemplo "" => 0 o "1" => 1 o "1,2" => 3.
     * Paso 2 (NORMAL MODE)
     * El método add puede manejar una cantidad ilimitada de números
     * El método puede manejar saltos de líneas en vez de comas
     * Las siguientes entradas son válidas:
     * 1\n2,3
     * 1\n2\n3
     * Entradas no válidas
     * 1,\n (Dado que no hay un número con que sumar)
     */

    private ArrayList<Character> operators;

    public StringCalc() {
        this.operators = new ArrayList<Character>();
        this.operators.add(',');
        this.operators.add('\n');
    }

    public boolean is_operator(Character cadena) {
        for (Iterator<Character> it = operators.iterator(); it.hasNext();) {
            Character ope = it.next();
            if (ope.equals(cadena)) {
                return true;
            }
        }
        return false;
    }

    public String add(String operation) throws IllegalArgumentException {
        if (operation.equals("")) {
            return "0";
        }
        if (operation.startsWith("//")) {
            if (operation.charAt(3) == '\n') {
                System.out.println(operation.charAt(2));
                this.setDefaultOperator(operation.charAt(2));
                operation = operation.substring(4);
            } else {
                throw new IllegalArgumentException("Delimitacion invalida");
            }
        }else{
            this.setDefaultOperator(',');
        }
        char[] coperation = operation.toCharArray();
        StringBuilder numero = new StringBuilder();
        long n;
        ArrayList<String> numeros = new ArrayList<String>();
        for (int i = 0; i < coperation.length; i++) {
            if (!this.is_operator(coperation[i])) {
                numero.append(coperation[i]);
                continue;
            } else {
                if (numero.toString().equals("")) {
                    throw new IllegalArgumentException("Operacion invalido");
                } else {
                    numeros.add(numero.toString());
                    numero.delete(0, numero.length());
                }
            }
        }
        numeros.add(numero.toString());
        long resultado = 0;
        for (Iterator<String> it = numeros.iterator(); it.hasNext();) {
            String num = it.next();
            n = Long.parseLong(num);
            if (n < 0) {
                throw new IllegalArgumentException("Operacion invalido");
            }
            resultado += n;
        }
        return String.valueOf(resultado);
    }

    public void setDefaultOperator(Character operator) {
        this.operators.set(0, operator);
    }
}
